using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.WebControls;
using System.Data;

namespace TST.SharePoint.Shared.WebControls
{
    public class SharePointCalendar : Control
    {
        private Exception _exception = null;
        private GridDatasource _datasource;
        private DatasourceConfiguration _configuration;
        private List<IFilterValues> _filterProviders;
        private SPCalendarView _view;

        public SharePointCalendar(GridDatasource datasource, DatasourceConfiguration configuration)
        {
            _filterProviders = new List<IFilterValues>();
            _datasource = datasource;
            _configuration = configuration;
        }

        public GridDatasource GridDatasource
        {
            get { return _datasource; }
            set
            {
                _datasource = value;
                ResetConfiguration();
            }
        }

        public DatasourceConfiguration Configuration
        {
            get { return _configuration; }
            set
            {
                _configuration = value;
                if (_datasource != null)
                {
                    _datasource.Configuration = _configuration;
                }
                ResetConfiguration();
            }
        }

        private void ResetConfiguration()
        {
        }

        /// <summary>
        /// Create the SharePoint calendar. Uses the SharePoint SPCalendarView object.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            _view = new SPCalendarView();
            _view.EnableViewState = true;
            _view.Width = Unit.Percentage(100);
            Controls.Add(_view);
            if (Page.Request.QueryString["CalendarPeriod"] != null)
            {
                switch (Page.Request.QueryString["CalendarPeriod"].ToString().ToLower())
                {
                    case "day":
                        _view.ViewType = "day";
                        break;
                    case "week":
                        _view.ViewType = "week";
                        break;
                    case "timeline":
                        _view.ViewType = "timeline";
                        break;
                    default:
                        _view.ViewType = "month";
                        break;
                }
            }
        }

        private SPCalendarItemCollection GetCalendarItems()
        {
            SPCalendarItemCollection items = new SPCalendarItemCollection();
            if (GridDatasource != null)
            {
                if (Field.IsFieldId(Configuration.StartDateField) && GridDatasource.Fields.Contains(Configuration.StartDateField) &&
                    Field.IsFieldId(Configuration.TitleField) && GridDatasource.Fields.Contains(Configuration.TitleField))
                {
                    DataTable table = GridDatasource.GetData();
                    foreach (DataRow row in table.Rows)
                    {
                        if (row[GridDatasource.Fields[Configuration.StartDateField].Name].GetType() != typeof(System.DBNull) &&
                            row[GridDatasource.Fields[Configuration.TitleField].Name].GetType() != typeof(System.DBNull))
                        {
                            SPCalendarItem item = new SPCalendarItem();
                            item.StartDate = (DateTime)row[GridDatasource.Fields[Configuration.StartDateField].Name];
                            if (Field.IsFieldId(Configuration.EndDateField) &&
                                GridDatasource.Fields.Contains(Configuration.EndDateField) &&
                                row[GridDatasource.Fields[Configuration.EndDateField].Name].GetType() != typeof(System.DBNull))
                            {
                                item.EndDate = (DateTime)row[GridDatasource.Fields[Configuration.EndDateField].Name];
                                item.hasEndDate = true;
                            }
                            else
                            {
                                item.hasEndDate = false;
                            }
                            item.Title = row[GridDatasource.Fields[Configuration.TitleField].Name].ToString();

                            string siteUrl = SPContext.Current.Site.Url;
                            if (siteUrl == "/")
                                siteUrl = string.Empty;
                            string link = string.Empty;
                            if (Field.IsFieldId(Configuration.Fields[Configuration.TitleField].LinkFieldId))
                            {
                                Field field = GridDatasource.Fields[Configuration.Fields[Configuration.TitleField].LinkFieldId];
                                if (field != null && row[field.Id] != null)
                                    link = row[field.Id].ToString().ToLower().Replace(siteUrl.ToLower(), string.Empty);
                            }
                            if (string.IsNullOrEmpty(link))
                            {
                                if (row["LinkUrl"] == null || row["LinkUrl"].ToString() == string.Empty)
                                    link = siteUrl;
                                else
                                    link = row["LinkUrl"].ToString().ToLower().Replace(siteUrl.ToLower(), string.Empty);
                            }
                            string urlStart = SPContext.Current.Site.ServerRelativeUrl;
                            if (urlStart == "/")
                                urlStart = string.Empty;
                            link = string.Format("{0}/_layouts/tst/tstredirect.aspx?GoTo={1}", urlStart, System.Web.HttpUtility.UrlEncode(link));

                            item.DisplayFormUrl = link;

                            if (Field.IsFieldId(Configuration.LocationField) &&
                                GridDatasource.Fields.Contains(Configuration.LocationField) &&
                                row[GridDatasource.Fields[Configuration.LocationField].Name] != null)
                            {
                                item.Location = row[GridDatasource.Fields[Configuration.LocationField].Name].ToString();
                            }
                            if (Field.IsFieldId(Configuration.DescriptionField) &&
                                GridDatasource.Fields.Contains(Configuration.DescriptionField) &&
                                row[GridDatasource.Fields[Configuration.DescriptionField].Name] != null)
                            {
                                item.Description = row[GridDatasource.Fields[Configuration.DescriptionField].Name].ToString();
                            }
                            if (Field.IsFieldId(Configuration.IsAllDayField) &&
                                GridDatasource.Fields.Contains(Configuration.IsAllDayField) &&
                                row[GridDatasource.Fields[Configuration.IsAllDayField].Name] != null)
                            {
                                string s = row[GridDatasource.Fields[Configuration.IsAllDayField].Name].ToString();
                                item.IsAllDayEvent = (s == "1");
                            }
                            item.IsRecurrence = false;
                            item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);

                            items.Add(item);
                        }
                    }
                }
            }
            return items;
        }

        protected override void OnInit(EventArgs args)
        {
            base.OnInit(args);
        }

        /// <summary>
        /// PreRender; databind the calendar.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            SetFilters();

            if (!Configuration.JustSearchOnQuery || HasQuery)
            {
                _view.DataSource = GetCalendarItems();
                DataBind();
            }
            base.OnPreRender(e);
        }

        private bool HasQuery
        {
            get
            {
                return (GridDatasource != null && Configuration.Filters.Count > 0);
            }
        }

        private void SetFilters()
        {
            // Setup Filters
            if (FilterProviders.Count > 0)
            {
                foreach (IFilterValues filter in FilterProviders)
                {
                    if (filter != null && filter.ParameterValues != null &&
                        GridDatasource.Fields.GetFieldsWithDisplayName(filter.ParameterName) != null)
                    {
                        foreach (Field f in GridDatasource.Fields.GetFieldsWithDisplayName(filter.ParameterName))
                        {
                            TST.SharePoint.Shared.Filter newfilter = new Filter(f);
                            foreach (string val in filter.ParameterValues)
                            {
                                newfilter.FilterValues.Add(new FilterValue(val));
                            }
                            Configuration.Filters.Add(newfilter);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// If there has been an exception, render the message; otherwise render the grid.
        /// </summary>
        /// <param name="writer"></param>
        protected override void Render(HtmlTextWriter writer)
        {
            if (_exception != null)
            {
                writer.WriteLine(string.Format("Error while loading the data: {0}<br>", _exception.Message));
                writer.WriteLine(string.Format("Exception: {0}", _exception.GetType().FullName));
                if (_exception.InnerException != null)
                {
                    writer.WriteLine(string.Format("Inner exception: {0}<br>", _exception.InnerException.Message));
                    writer.WriteLine(string.Format("Inner exception: {0}", _exception.InnerException.GetType().FullName));
                }
            }
            else
            {
                base.Render(writer);
            }
        }

        public List<IFilterValues> FilterProviders
        {
            get { return _filterProviders; }
            set { _filterProviders = value; }
        }

    }
}
